package com.snapan.service.impl;

import com.snapan.entity.FileBase;
import com.snapan.service.FileBaseService;
import com.snapan.service.PdfService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.nio.file.*;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.UUID;

/**
 * 简单实现：把 `/uploads/...` 映射到项目根目录下 ./files/uploads/...
 * 保存策略：另存为 新文件 名称格式为 {origName}_edit_{yyyyMMddHHmmss}.pdf
 */
@Service
public class PdfServiceImpl implements PdfService {

    @Autowired
    private FileBaseService fileBaseService;

    private static final String PROJECT_BASE_FILES = "./files"; // 项目根目录下 files 文件夹
    private static final String DB_PREFIX = "/uploads"; // 数据库里路径前缀用于映射

    @Override
    public File resolvePhysicalFile(String dbPath) {
        if (dbPath == null) return null;

        // 如果数据库里存的是绝对路径（例如以盘符或 / 开头），但我们约定：若以 "/uploads" 开头则映射到 ./files
        if (dbPath.startsWith(DB_PREFIX)) {
            String relative = dbPath.substring(1); // remove leading '/'
            Path path = Paths.get(PROJECT_BASE_FILES, relative); // ./files/uploads/...
            return path.toFile();
        } else {
            // 如果是相对路径或已填绝对路径
            Path path = Paths.get(PROJECT_BASE_FILES, dbPath);
            File f = path.toFile();
            if (f.exists()) return f;
            // fallback: try raw path
            return new File(dbPath);
        }
    }

    @Override
    public Long saveAsNewFile(Long originalFileId, MultipartFile file, Integer userId) throws Exception {
        // 1. 找到原文件的 FileBase 用于获取路径结构和文件名
        FileBase original = fileBaseService.getById(originalFileId);
        if (original == null) {
            throw new FileNotFoundException("原文件不存在，id=" + originalFileId);
        }

        String origRealName = original.getRealName();
        if (origRealName == null || origRealName.trim().isEmpty()) {
            origRealName = "file";
        }
        String baseName = origRealName;
        // remove suffix if present
        int dot = baseName.lastIndexOf('.');
        if (dot > 0) baseName = baseName.substring(0, dot);

        // 2. 生成新文件名与目录结构：保持与原文件相同的 db path 目录结构
        String origDbPath = original.getFilePath(); // e.g. /uploads/documents/report.pdf
        String dirPart = "/uploads";
        if (origDbPath != null && origDbPath.lastIndexOf('/') > 0) {
            dirPart = origDbPath.substring(0, origDbPath.lastIndexOf('/')); // /uploads/documents
        }

        // timestamp
        String ts = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date());
        String newFileName = baseName + "_edit_" + ts + ".pdf";

        // db path for new file
        String newDbRelativePath = dirPart + "/" + newFileName; // /uploads/documents/report_edit_2025...
        // physical path -> ./files/uploads/documents/report_edit_xxxx.pdf
        Path physicalDir = Paths.get(PROJECT_BASE_FILES, dirPart.substring(1)); // drop leading '/'
        Files.createDirectories(physicalDir);

        Path physicalFile = physicalDir.resolve(newFileName);

        // 3. 保存文件到磁盘
        try (InputStream in = file.getInputStream()) {
            Files.copy(in, physicalFile, StandardCopyOption.REPLACE_EXISTING);
        }

        // 4. 创建新的 FileBase 记录并保存（调用现有的 fileBaseService）
        FileBase newFb = new FileBase();
        newFb.setRealName(newFileName);
        // storage file name (unique stored name)
        String storageName = UUID.randomUUID().toString() + "_" + newFileName;
        newFb.setFileName(storageName);
        newFb.setSuffix("pdf");
        newFb.setFileMd5(null); // 可选：后面补充 MD5 功能
        newFb.setFileSize(Files.size(physicalFile));
        newFb.setFileType("application/pdf");
        newFb.setFilePath(newDbRelativePath); // 存相对路径到 DB (/uploads/...)
        newFb.setChunkCount(1);
        newFb.setChunkSize(newFb.getFileSize());
        newFb.setStatus((byte) 1);
        newFb.setCreateBy(userId == null ? "system" : ("user_" + userId));
        newFb.setCreateTime(new Date());
        newFb.setUpdateBy(newFb.getCreateBy());
        newFb.setUpdateTime(new Date());

        boolean added = fileBaseService.add(newFb); // 你的实现返回 boolean
        Long newId = null;

        // 尝试获取新增记录的 id（若你的 service 可以提供按 path 查询，可改用更可靠逻辑）
        try {
            // 假设 fileBaseService 有 getByMD5AndSize 或 getByFilePath 方法 —— 如果没有请忽略或实现你项目自己的查询
            FileBase existed = fileBaseService.getByMD5AndSize(newFb.getFileMd5(), newFb.getFileSize());
            if (existed != null) newId = existed.getId();
        } catch (Throwable ignored) {
        }

        // 如果无法通过上面方法得到 id，尝试返回 null（前端仍然会收到 success）
        return newId;
    }

    @Override
    public String saveImageTemp(MultipartFile image) throws Exception {
        if (image == null || image.isEmpty()) {
            throw new IllegalArgumentException("图片为空");
        }
        String orig = image.getOriginalFilename();
        String ext = "png";
        if (orig != null && orig.contains(".")) {
            ext = orig.substring(orig.lastIndexOf('.') + 1);
        }
        String name = UUID.randomUUID().toString() + "." + ext;
        Path tempDir = Paths.get(PROJECT_BASE_FILES, "uploads", "temp");
        Files.createDirectories(tempDir);
        Path target = tempDir.resolve(name);
        try (InputStream in = image.getInputStream()) {
            Files.copy(in, target, StandardCopyOption.REPLACE_EXISTING);
        }
        // 返回数据库存储相对路径（以 /uploads/... 形式）
        return "/uploads/temp/" + name;
    }
}
